package com.geek.bulk.interceptor;

import com.geek.bulk.util.TimeUtils;
import org.eclipse.microprofile.faulttolerance.Timeout;
import org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException;

import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * 超时与重试（Timeout and Retry）
 */
@Interceptor
public class TimeOutInterceptor extends AnnotatedInterceptor<Timeout> {

    private final ExecutorService executorService = ForkJoinPool.commonPool();

    @Override
    protected Object execute(InvocationContext context, Timeout timeout) {
        ChronoUnit unit = timeout.unit();
        long value = timeout.value();
        TimeUnit timeUnit = TimeUtils.toTimeUnit(unit);

        Future<Object> future = executorService.submit(context::proceed);
        try {
            return future.get(value, timeUnit);
        } catch (Exception e) {
            throw new TimeoutException(e);
        }
    }
}
